# # 联合循环电厂数据回归分析
# Combined Cycle Power Plant Data Set （数据来自UCI Machine Learning Repository）
# 该数据集包含了从一个联合循环电厂(2006-2011)满负荷运行6年期间收集的9568个数据点。特征包括每小时平均环境温度(AT，单位为摄氏度)、环境压力(AP，单位为毫巴milibar)、相对湿度(RH，为百分比)和排气真空程度(V，单位为厘米汞柱)，以预测电厂每小时净电能输出(PE，兆瓦MW)。

# ## 步骤1：读取数据

# In[1]:


import pandas as pd

# pd.read_excel()默认读取第0个sheet的数据
# 如果不是在anaconda环境下，需要先安装openpyxl
ccpp_data = pd.read_excel(
    index_col=None, io="data/Combined_Cycle_Power_Plant_Data_Set.xlsx"
)

print(ccpp_data[:3])

X = ccpp_data.iloc[:, :4].values.astype(float)
y = ccpp_data.iloc[:, -1:].values.astype(float)

print(X.shape)
print(y.shape)
print(X[:3])
print(y[:3])


# ## 步骤2：划分训练集与测试集

# In[2]:


from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

print(X_train.shape)
print(X_test.shape)


# ## 步骤3：通过训练数据相关性分析或训练数据可视化，观察训练数据的基本关系

# In[3]:


import numpy as np
import matplotlib.pylab as plt

train_array = np.hstack((X_train, y_train))

train_df = pd.DataFrame(train_array, columns=ccpp_data.columns)
# print(train_df[:3])

# 通过corr()方法计算每对属性之间的标准关系系数（皮尔逊系数）
corr_matrix = train_df.corr()
print("皮尔逊系数矩阵：\n", corr_matrix)
# 查看各特征属性与目标值之间的相关性
print(
    "各特征属性与每小时电量输出之间的关系：\n",
    corr_matrix["PE"].sort_values(ascending=False),
    sep="",
)

# 分别绘制各个自变量与目标变量之间的散点图
# print(ccpp_data.columns[:-1])
plt.rcParams["font.sans-serif"] = ["SimHei"]  # 用来正常显示中文
plt.rcParams["axes.unicode_minus"] = False  # 用来正常显示负号
d = {
    "AT": "环境温度",
    "AP": "环境压力",
    "RH": "相对湿度",
    "V": "排气真空程度",
    "PE": "输出电能",
}
y_col_name = ccpp_data.columns[-1:][0]

"""
# 在四个图形中输出
for col in  ccpp_data.columns[:-1]:
    train_df.plot(kind="scatter", x=col, y=y_col_name,
                  title=f"属性{col}({d[col]})和电能输出(兆瓦MW)的关系")
    plt.xlabel(xlabel=f"{col}:{d[col]}")
    plt.ylabel(ylabel=f"{y_col_name}:{d[y_col_name]}")
"""
# 在一个图形的四个子图中输出
fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(11, 7))
for ax, col_name in zip(axes.ravel(), ccpp_data.columns[:-1]):
    print(type(train_df[col_name]))
    ax.scatter(x=np.array(train_df[col_name]), y=np.array(train_df[y_col_name]))
    # 选择当前子图
    plt.sca(ax)
    # 设置刻度字体大小
    plt.xticks(fontsize=15)
    plt.yticks(fontsize=15)
    # 为每个子图设置横纵轴标的标签
    plt.xlabel(xlabel=f"{col_name}:{d[col_name]}", fontsize=15)
    plt.ylabel(ylabel=f"{y_col_name}:{d[y_col_name]}", fontsize=15)

# 调整子图间距：wspace为横向间距，hspace为纵向间距
plt.subplots_adjust(wspace=0.3, hspace=0.5)
plt.show()

"""
#也可以使用scatter_matrix来绘制
from pandas.plotting import scatter_matrix
scatter_matrix(train_df, figsize=(12,10))
plt.show()
"""


# ## 步骤4：以线性回归为例来训练模型

# In[4]:


# 建立自变量特征值与目标变量之间的线性回归模型
from sklearn.linear_model import LinearRegression

m = LinearRegression()
m.fit(X_train, y_train)
# 输出线性回归模型的截距与回归系数
print(m.intercept_, m.coef_)


# ## 步骤5：评估模型

# In[5]:


# 评估模型性能
from sklearn import metrics

y_train_pred = m.predict(X_train)
y_test_pred = m.predict(X_test)
# 均方误差
train_mean_squared_error = metrics.mean_squared_error(y_train, y_train_pred)
test_mean_squared_error = metrics.mean_squared_error(y_test, y_test_pred)
print("训练集的均方误差：{:.2f}".format(train_mean_squared_error))
print("测试集的均方误差：{:.2f}".format(test_mean_squared_error))
# 决定系数
test_predict_score = m.score(X_test, y_test)
print("决定系数：{:.2f}".format(test_predict_score))


# ## 步骤6：用新的数据来预测电能输出

# In[6]:


X_new = np.array([[15, 42, 1024, 73], [5, 40, 1012, 92]])
print("预测的电能输出为：{}".format(m.predict(X_new)))
